﻿using Mapster;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using XYS.Core.Api.Middlewares;
using XYS.Core.Models;
using XYS.Core.Util;
using XYS.Core.Util.Helper;
using XYS.Service.Core.Filters;
using XYS.Service.Core.Service;
using XYS.Service.Core.Util.Conventions;
using XYS.Service.Core.Util.Helper;

namespace XYS.Service.Core
{
    /// <summary>
    /// 
    /// </summary>
    public static class WebApplicationBuilderExtension
    {
        /// <summary>
        /// 添加核心功能
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="loggerFactory"></param>
        /// <returns></returns>
        public static WebApplicationBuilder AddCore(this WebApplicationBuilder builder, ILoggerFactory loggerFactory = null)
        {
            loggerFactory ??= LoggerFactoryHelper.CreateLoggerFactory();

            //添加long转换器
            Extention.jsonSerializerSettings.Converters.Add(new Util.Converters.LongToStringConverter());
            Extention.jsonSerializerSettings.Converters.Add(new Util.Converters.LongCanNullToStringConverter());
            Extention.jsonSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.ExpandoObjectConverter());

            var logger = loggerFactory.CreateLogger("XYS.Core");

            //初始化程序集内容
            AssemblyHelper.GetAssemblyTypes();

            GlobalCoreSetting.XYSCoreDLLVersion = AssemblyHelper.GetAssemblyVersion(typeof(WebApplicationBuilderExtension).Assembly);

            //忽略 自动映射时 大小写敏感
            TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy(NameMatchingStrategy.Flexible);

            logger.LogWarning($"Core 版本号为【{GlobalCoreSetting.XYSCoreDLLVersion}】");

            //读取环境变量
            GlobalCoreSetting.EnvironmentName = builder.Environment.EnvironmentName;
            logger.LogInformation($"EnvironmentName: {GlobalCoreSetting.EnvironmentName}");

            //注册配置中心。
            //*必须先注册配置中心。 否则后面的功能可能会拿不到配置
            builder.AddConfigurationCenter(loggerFactory.CreateLogger("AddConfigurationCenter"));

            //添加 ELK
            builder.AddELK(loggerFactory);

            //注册上下文：AOP里面可以获取IOC对象，
            builder.Services.AddHttpContextAccessor();

            //映射全局参数
            builder.AddGlobalSetting(typeof(GlobalCoreSetting));

            //当前服务的名称
            if (string.IsNullOrWhiteSpace(GlobalCoreSetting.ServiceName))
            {
                logger.LogError("缺少配置项：ServiceName");
                throw new Exception("缺少配置项：ServiceName");
            }

            //获取RSA的公钥和秘钥
            EncryptHelper.RSAPrivateKey = GlobalCoreSetting.RSAKeySetting.PrivateKey_XML;
            EncryptHelper.RSAPublicKey = GlobalCoreSetting.RSAKeySetting.PublicKey_XML;

            //ES 客户端配置
            builder.AddElastic(logger);

            //真实IP配置
            builder.Services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
            });

            //配置拦截器,Json序列化配置等
            builder.Services
                .AddControllers(options =>
                {
                    options.Conventions.Add(new ControllerModelConvention());
                    options.Conventions.Add(new ApplicationModelConvention());
                    options.Filters.Add<APIResultEnumDescFilter>();
                })
                .AddNewtonsoftJson(m =>
            {
                //忽略循环引用
                m.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                //使用驼峰样式
                m.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                //值为null时则忽略映射
                m.SerializerSettings.NullValueHandling = GlobalCoreSetting.ResultIgnoreNullValue ? NullValueHandling.Ignore : NullValueHandling.Include;

                //深度级别
                m.SerializerSettings.MaxDepth = 64;

                if (Extention.jsonSerializerSettings.Converters != null && Extention.jsonSerializerSettings.Converters.Count > 0)
                    m.SerializerSettings.Converters = Extention.jsonSerializerSettings.Converters;

                //保存序列化配置
                Extention.jsonSerializerSettings = m.SerializerSettings;
            });

            //配置缓存
            builder.AddCache(loggerFactory.CreateLogger("AddCache"));

            //配置 XXLJob
            builder.AddXXLJob(loggerFactory.CreateLogger("AddXXLJob"));

            //自动注入服务
            builder.AddScopedService();

            //gRpc
            builder.AddGRpc(loggerFactory.CreateLogger("AddGRpc"));

            //使用 Http1AndHttp2 协议
            builder.WebHost.ConfigureKestrel(option =>
            {
                option.ConfigureEndpointDefaults(o =>
                {
                    o.Protocols = HttpProtocols.Http1AndHttp2;
                });
            });

            //配置 API 请求日志记录者
            builder.AddApiLogger(loggerFactory);
            //配置 HTTP 请求日志记录者
            builder.AddHttpLogger(loggerFactory.CreateLogger("AddHttpLogger"));

            //路由地址使用小写
            builder.Services.AddRouting(options => options.LowercaseUrls = true);

            //自动处理接口返回模型
            builder.Services.AddTransient<IApplicationModelProvider, ProduceResponseTypeModelProvider>();

            //注册过滤器
            builder.Services.AddControllersWithViews(options =>
            {
                options.Filters.Add<DateTimeOffsetValueFilters>();
                options.Filters.Add<StringValueFilters>();
            });

            //配置 MQ 消息队列
            builder.AddMQ(logger);

            //对象存储
            builder.AddOSS(logger);

            //添加端口侦听配置
            builder.AddListen();

            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();

            //注入当前登录用户
            builder.Services.AddScoped(s =>
            {
                try
                {
                    var context = s.GetService<IHttpContextAccessor>();
                    if (context == null || context.HttpContext == null) return CurrentUserInfo.CreateAnonymousUser();

                    context.HttpContext.Request.Headers.TryGetValue("deviceFingerprint", out StringValues deviceFingerprint);

                    string token = TokenHelper.GetToken(context.HttpContext?.Request);
                    if (string.IsNullOrWhiteSpace(token))
                    {
                        var result = CurrentUserInfo.CreateAnonymousUser();
                        result.DeviceFingerprint = deviceFingerprint;
                        return result;
                    }

                    var currentUserInfo = TokenHelper.ReadToken(token);
                    if (currentUserInfo == null || currentUserInfo.IsAnonymous())
                    {
                        var result = CurrentUserInfo.CreateAnonymousUser();
                        result.DeviceFingerprint = deviceFingerprint;
                        return result;
                    }

                    currentUserInfo.IsFake = context.HttpContext.Request.Headers.ContainsKey("Fake");
                    if (deviceFingerprint != "" && currentUserInfo.DeviceFingerprint != deviceFingerprint)
                        currentUserInfo.DeviceFingerprint = deviceFingerprint;

                    CurrentUserInfo.CurrentUserService ??= s.GetService<ICurrentUserService>();
                    return currentUserInfo;
                }
                catch { return CurrentUserInfo.CreateAnonymousUser(); }
            });

            //增加jwt配置
            builder.AddJWTSetting(loggerFactory);

            //添加事件总线
            builder.AddEventBus(logger);

            //自动配置swagger
            builder.AddSwagger();

            return builder;
        }

    }
}
